package com.skt.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.skt.domain.DTO.RentalOrderDTO;
import com.skt.domain.DTO.request.RentalCalculateRequest;
import com.skt.domain.DTO.request.RentalCheckoutRequest;
import com.skt.domain.PO.CartItem;
import com.skt.domain.PO.Costume;
import com.skt.domain.VO.AmountInfoVO;
import com.skt.domain.VO.PaymentInfoVO;
import com.skt.domain.VO.RentalCalculateVO;
import com.skt.domain.VO.RentalCheckoutVO;
import com.skt.exception.*;
import com.skt.mapper.CartItemMapper;
import com.skt.mapper.CostumeMapper;
import com.skt.service.RentalService;
import com.skt.utils.LogUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

@Service
@Slf4j
@RequiredArgsConstructor
public class RentalServiceImpl implements RentalService {

    private final CartItemMapper cartItemMapper;
    private final CostumeMapper costumeMapper;


    private RentalCheckoutRequest currentRequest; // 用于存储当前请求

    // 押金比例（可根据业务调整）
    private static final BigDecimal DEPOSIT_RATIO = new BigDecimal("0.3");

    /**
     * 服装租赁费用计算
     */
    @Override
    public RentalCalculateVO calculateRentalCost(RentalCalculateRequest request) {
        try {

            // 1. 参数校验
            validateCalculateParam(request);

            // 2. 获取有效地购物车项
            List<CartItem> validCartItems = getValidCartItemsFromDatabase(request.getCartItemIds());

            // 3. 计算租赁天数
            long rentalDays = calculateRentalDays(request.getStartDate(), request.getEndDate());

            // 4. 计算各项费用
            List<RentalCalculateVO.CalculateItemVO> details = calculateRentalDetails(validCartItems, rentalDays);
            BigDecimal totalRentalAmount = calculateTotalRentalAmount(details);
            BigDecimal depositAmount = calculateDepositAmount(totalRentalAmount);
            BigDecimal totalAmount = totalRentalAmount.add(depositAmount);

            // 5. 构建返回结果
            RentalCalculateVO result = buildRentalCalculateResult(
                    request, details, totalRentalAmount, depositAmount, totalAmount, rentalDays);

            LogUtil.info("RENTAL", "CALCULATE", "租赁费用计算完成: 租金={}, 押金={}, 总计={}",
                    totalRentalAmount, depositAmount, totalAmount);
            return result;

        } catch (BusinessException e) {
            LogUtil.error("RENTAL", "CALCULATE", "租赁费用计算失败: error={}", e.getMessage());
            throw e;
        } catch (Exception e) {
            LogUtil.error("RENTAL", "CALCULATE", "租赁费用计算异常", e);
            throw RentalException.of(RentalErrorCode.CALCULATION_FAILED);
        }
    }


    /**
     * 租赁结算下单
     */
    @Override
    public RentalCheckoutVO createRentalOrder(RentalCheckoutRequest request) {
        try {
            this.currentRequest = request; // 保存请求对象供其他方法使用

            // 第一步：基础参数校验
            validateBasicParams(request);

            // 第二步：验证计算凭证有效性
            RentalCalculateVO calculateResult = validateCalculateResult(request.getCalculateId());

            // 第三步：创建订单记录
            RentalOrderDTO orderDTO = createOrderRecord(request, calculateResult);

            // 第四步：构建返回结果
            RentalCheckoutVO checkoutResult = buildCheckoutResult(orderDTO, calculateResult);

            LogUtil.info("RENTAL", "CHECKOUT", "租赁结算下单完成: orderId={}", checkoutResult.getOrderId());
            return checkoutResult;

        } catch (BusinessException e) {
            LogUtil.error("RENTAL", "CHECKOUT", "租赁结算下单失败: error={}", e.getMessage());
            throw e;
        } catch (Exception e) {
            LogUtil.error("RENTAL", "CHECKOUT", "租赁结算下单异常", e);
            throw new RentalException(RentalErrorCode.ORDER_CREATE_FAILED, "订单创建失败");
        } finally {
            this.currentRequest = null; // 清理请求对象
        }
    }

    /**
     * 第一步：基础参数校验
     */
    private void validateBasicParams(RentalCheckoutRequest request) {

        if (request == null) {
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "请求参数不能为空");
        }

        if (request.getContactInfo() == null) {
            throw ValidationException.of(ValidationErrorCode.FIELD_REQUIRED,"联系信息不能为空");
        }

        if (!isValidPhoneNumber(request.getContactInfo().getPhone())) {
            throw ValidationException.of(ValidationErrorCode.FIELD_REQUIRED,"手机号格式不正确");
        }
    }

    /**
     * 创建订单记录
     */
    private RentalOrderDTO createOrderRecord(RentalCheckoutRequest request, RentalCalculateVO calculateResult) {
        try {
            LogUtil.info("RENTAL", "CREATE_ORDER", "开始创建订单记录");

            // 创建订单DTO
            RentalOrderDTO orderDTO = buildRentalOrderDTO(request, calculateResult);

            // 这里应该调用Mapper保存到数据库
            // int result = rentalOrderMapper.insert(orderDTO);
            // if (result <= 0) {
            //     throw new BusinessException("订单创建失败");
            // }

            LogUtil.info("RENTAL", "CREATE_ORDER", "订单记录创建成功, orderNo: {}", orderDTO.getOrderNo());
            return orderDTO;

        } catch (Exception e) {
            LogUtil.error("RENTAL", "CREATE_ORDER", "创建订单记录失败", e);
            throw new BusinessException(RentalErrorCode.ORDER_CREATE_FAILED.getCode(), "订单创建失败，请稍后重试");
        }
    }

    /**
     * 验证计算凭证有效性 - 适配RentalCalculateVO结构
     */
    private RentalCalculateVO validateCalculateResult(String calculateId) {
        if (StringUtils.isBlank(calculateId)) {
            throw new BusinessException(RentalErrorCode.INVALID_RENTAL_REQUEST.getCode(), "计算凭证无效");
        }

        // TODO 模拟数据

        // 这里应该从缓存或数据库获取计算结果
        // 模拟返回计算结果，匹配RentalCalculateVO结构
        RentalCalculateVO calculateResult = new RentalCalculateVO();
        calculateResult.setTotalRentalAmount(new BigDecimal("500.00"));
        calculateResult.setDepositAmount(new BigDecimal("250.00"));
        calculateResult.setTotalAmount(new BigDecimal("750.00"));
        calculateResult.setTotalDays(7);

        // 设置计算明细
        List<RentalCalculateVO.CalculateItemVO> details = new ArrayList<>();

        // 模拟明细项1
        RentalCalculateVO.CalculateItemVO item1 = new RentalCalculateVO.CalculateItemVO();
        item1.setCostumeId(1L);
        item1.setMerchantId(1L);
        item1.setCostumeName("汉服-唐装");
        item1.setQuantity(2);
        item1.setRentalDays(7);
        item1.setDailyPrice(new BigDecimal("35.00"));
        item1.setSubtotal(new BigDecimal("490.00"));
        details.add(item1);

        // 模拟明细项2
        RentalCalculateVO.CalculateItemVO item2 = new RentalCalculateVO.CalculateItemVO();
        item2.setCostumeId(2L);
        item2.setMerchantId(2L);
        item2.setCostumeName("旗袍");
        item2.setQuantity(1);
        item2.setRentalDays(7);
        item2.setDailyPrice(new BigDecimal("10.00"));
        item2.setSubtotal(new BigDecimal("70.00"));
        details.add(item2);

        calculateResult.setDetails(details);

        LogUtil.info("RENTAL", "VALIDATE_CALCULATE", "计算凭证验证通过: {}", calculateId);
        return calculateResult;
    }

    /**
     * 构建订单DTO - 使用RentalCalculateVO中的数据
     */
    private RentalOrderDTO buildRentalOrderDTO(RentalCheckoutRequest request, RentalCalculateVO calculateResult) {
        RentalOrderDTO orderDTO = new RentalOrderDTO();

        // 生成订单编号
        String orderNo = generateOrderNo();

        // 设置DTO字段
        orderDTO.setOrderNo(orderNo);
        orderDTO.setUserId(getCurrentUserId());

        // 设置租赁日期（根据业务逻辑计算）
        LocalDate startDate = LocalDate.now().plusDays(1);
        LocalDate endDate = startDate.plusDays(calculateResult.getTotalDays());

        orderDTO.setStartDate(startDate);
        orderDTO.setEndDate(endDate);
        orderDTO.setTotalDays(calculateResult.getTotalDays());

        // 设置金额（使用RentalCalculateVO中的金额字段）
        orderDTO.setTotalAmount(calculateResult.getTotalAmount());

        // 设置状态：1-待支付
        orderDTO.setStatus(1);

        // 设置时间戳
        orderDTO.setCreatedAt(LocalDateTime.now());
        orderDTO.setUpdatedAt(LocalDateTime.now());

        // 备注可以存储联系信息和商品信息
        StringBuilder remarkBuilder = new StringBuilder();
        if (request.getContactInfo() != null) {
            remarkBuilder.append("联系人:")
                    .append(request.getContactInfo().getName())
                    .append(", 电话:")
                    .append(request.getContactInfo().getPhone());
        }

        // 添加商品信息到备注
        if (calculateResult.getDetails() != null && !calculateResult.getDetails().isEmpty()) {
            remarkBuilder.append(", 商品:");
            for (RentalCalculateVO.CalculateItemVO item : calculateResult.getDetails()) {
                remarkBuilder.append(item.getCostumeName())
                        .append("(").append(item.getQuantity()).append("件),");
            }
        }

        orderDTO.setRemark(remarkBuilder.toString());

        return orderDTO;
    }

    /**
     * 构建结算返回结果 - 使用RentalCalculateVO中的数据
     */
    private RentalCheckoutVO buildCheckoutResult(RentalOrderDTO orderDTO, RentalCalculateVO calculateResult) {
        RentalCheckoutVO checkoutResult = new RentalCheckoutVO();

        // 设置订单基本信息
        checkoutResult.setOrderId(orderDTO.getOrderNo());
        checkoutResult.setOrderStatus(getOrderStatusText(orderDTO.getStatus()));
        checkoutResult.setCreateTime(orderDTO.getCreatedAt().toString());

        // 设置金额信息 - 使用RentalCalculateVO中的金额字段
        AmountInfoVO amountInfo = new AmountInfoVO();
        amountInfo.setTotalAmount(calculateResult.getTotalAmount());
        amountInfo.setDepositAmount(calculateResult.getDepositAmount());
        amountInfo.setRentalAmount(calculateResult.getTotalRentalAmount());
        amountInfo.setDiscountAmount(BigDecimal.ZERO);
        checkoutResult.setAmountInfo(amountInfo);

        // 设置支付信息 - 简化版本，移除支付方式相关逻辑
        PaymentInfoVO paymentInfo = new PaymentInfoVO();
        paymentInfo.setPayAmount(calculateResult.getTotalAmount());
        paymentInfo.setExpireTime(LocalDateTime.now().plusMinutes(30).toString());

        // 移除支付方式判断和支付URL生成逻辑
        // 只保留基本的支付金额和过期时间
        checkoutResult.setPaymentInfo(paymentInfo);

        return checkoutResult;
    }

    /**
     * 生成订单编号
     */
    private String generateOrderNo() {
        return "RO" + System.currentTimeMillis() +
                String.format("%04d", ThreadLocalRandom.current().nextInt(1000));
    }

    /**
     * 将状态码转换为状态文本
     */
    private String getOrderStatusText(Integer statusCode) {
        if (statusCode == null) {
            return "unknown";
        }

        switch (statusCode) {
            case 1: return "pending_payment";
            case 2: return "paid";
            case 3: return "picked_up";
            case 4: return "returned";
            case 5: return "cancelled";
            default: return "unknown";
        }
    }

    /**
     * 工具方法
     */
    private boolean isPaymentMethodSupported(String paymentMethod) {
        return Arrays.asList("alipay", "wechat", "unionpay").contains(paymentMethod.toLowerCase());
    }

    private boolean isValidPhoneNumber(String phone) {
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }

    /**
     * 获取当前用户ID
     */
    private Long getCurrentUserId() {
        // 实际应该从安全上下文获取
        // 这里返回模拟用户ID
        return 10001L;
    }

    /**
     * 计算租赁明细
     */
    private List<RentalCalculateVO.CalculateItemVO> calculateRentalDetails(List<CartItem> cartItems,
                                                                           long rentalDays) {
        List<RentalCalculateVO.CalculateItemVO> details = new ArrayList<>();

        for (CartItem cartItem : cartItems) {
            RentalCalculateVO.CalculateItemVO itemVO = calculateSingleItemDetail(cartItem, rentalDays);
            details.add(itemVO);
        }

        return details;
    }

    /**
     * 计算单个商品租赁明细
     */
    private RentalCalculateVO.CalculateItemVO calculateSingleItemDetail(CartItem cartItem, long rentalDays) {
        // 1. 获取服装和商家信息
        Costume costume = getCostumeInfoFromDatabase(cartItem.getCostumeId());

        // 2. 计算小计金额
        BigDecimal subtotal = calculateSubtotal(cartItem.getDailyPrice(), rentalDays, cartItem.getQuantity());

        // 3. 构建明细VO
        RentalCalculateVO.CalculateItemVO itemVO = new RentalCalculateVO.CalculateItemVO();
        itemVO.setCostumeId(costume.getId());
        itemVO.setMerchantId(costume.getMerchantId());
        itemVO.setCostumeName(costume.getName());
        itemVO.setQuantity(cartItem.getQuantity());
        itemVO.setRentalDays((int) rentalDays);
        itemVO.setDailyPrice(cartItem.getDailyPrice());
        itemVO.setSubtotal(subtotal);

        return itemVO;
    }

    /**
     * 计算小计金额
     */
    private BigDecimal calculateSubtotal(BigDecimal dailyPrice, long rentalDays, Integer quantity) {
        int qty = quantity != null ? quantity : 1;
        return dailyPrice.multiply(BigDecimal.valueOf(rentalDays))
                .multiply(BigDecimal.valueOf(qty))
                .setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 计算总租金
     */
    private BigDecimal calculateTotalRentalAmount(List<RentalCalculateVO.CalculateItemVO> details) {
        return details.stream()
                .map(RentalCalculateVO.CalculateItemVO::getSubtotal)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 计算押金（租金的一定比例）
     */
    private BigDecimal calculateDepositAmount(BigDecimal totalRentalAmount) {
        return totalRentalAmount.multiply(DEPOSIT_RATIO)
                .setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 计算租赁天数
     */
    private long calculateRentalDays(LocalDate startDate, LocalDate endDate) {
        long days = ChronoUnit.DAYS.between(startDate, endDate);
        if (days <= 0) {
            throw RentalException.of(RentalErrorCode.RENTAL_DAYS_INVALID, "租赁天数必须大于0");
        }
        return days;
    }

    /**
     * 构建返回结果
     */
    private RentalCalculateVO buildRentalCalculateResult(RentalCalculateRequest request,
                                                         List<RentalCalculateVO.CalculateItemVO> details,
                                                         BigDecimal totalRentalAmount,
                                                         BigDecimal depositAmount,
                                                         BigDecimal totalAmount,
                                                         long rentalDays) {
        RentalCalculateVO result = new RentalCalculateVO();
        result.setTotalRentalAmount(totalRentalAmount);
        result.setDepositAmount(depositAmount);
        result.setTotalAmount(totalAmount);
        result.setTotalDays((int) rentalDays);
        result.setDetails(details);
        return result;
    }

    /**
     * 从数据库中批量获取有效的CartItem信息
     */
    private List<CartItem> getValidCartItemsFromDatabase(List<Long> cartItemIds) {

        // 1. id集合非空校验
        if (cartItemIds == null || cartItemIds.isEmpty()) {
            throw CartException.of(CartErrorCode.CART_IS_EMPTY);
        }

        // 2. 创建存放容器
        List<CartItem> validCartItems = new ArrayList<>();
        List<Long> invalidItemIds = new ArrayList<>();

        for (Long cartItemId : cartItemIds) {
            try {
                CartItem cartItem = cartItemMapper.selectById(cartItemId);
                if (cartItem == null) {

                    // 3. 收集无效  空的ID
                    invalidItemIds.add(cartItemId);
                    continue;
                }

                if (checkCartItem(cartItem)) {

                    // 4. 收集有效地购物车详情对象
                    validCartItems.add(cartItem);
                } else {

                    // 3. 收集无效  购物车详情对象不规范的ID
                    invalidItemIds.add(cartItemId);
                }
            } catch (Exception e) {
                LogUtil.warn("CART", "VALIDATE",
                        "购物车验证失败: cartItemId={}, error={}", cartItemId, e.getMessage());
                invalidItemIds.add(cartItemId);
            }
        }

        if (validCartItems.isEmpty()) {
            throw CartException.of(CartErrorCode.CART_ITEM_NOT_FOUND,
                    "购物车项无效或不存在: " + invalidItemIds);
        }

        if (!invalidItemIds.isEmpty()) {
            LogUtil.warn("CART", "VALIDATE",
                    "部分购物车项无效: {}", invalidItemIds);
        }

        return validCartItems;
    }

    /**
     * 购物车项验证
     */
    private boolean checkCartItem(CartItem cartItem) {
        // 1. 状态验证
        if (cartItem.getStatus() != 1) {
            throw CartException.of(CartErrorCode.CART_ITEM_INVALID, "购物车项状态无效");
        }

        // 2. 价格校验
        if (cartItem.getDailyPrice() == null ||
                cartItem.getDailyPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw CartException.of(CartErrorCode.INVALID_PRICE, "价格无效");
        }

        // 3. 数量校验
        if (cartItem.getQuantity() == null ||
                cartItem.getQuantity() <= 0 ||
                cartItem.getQuantity() > 999) {
            throw CartException.of(CartErrorCode.INVALID_QUANTITY, "数量无效");
        }

        // 4. 库存校验
        Costume costume = getCostumeInfoFromDatabase(cartItem.getCostumeId());
        if (costume.getStock() < cartItem.getQuantity()) {
            throw CostumeException.of(CostumeErrorCode.INSUFFICIENT_STOCK,
                    "商品【" + costume.getName() + "】库存不足，剩余库存: " + costume.getStock());
        }

        return true;
    }

    /**
     * 从数据库中查询服装信息
     */
    private Costume getCostumeInfoFromDatabase(Long costumeId) {
        try {
            Costume costume = costumeMapper.selectById(costumeId);
            if (costume == null) {
                throw CostumeException.of(CostumeErrorCode.COSTUME_NOT_FOUND,
                        "服装不存在: costumeId=" + costumeId);
            }

            // 检查服装状态
            if (costume.getStatus() != 1) {
                throw CostumeException.of(CostumeErrorCode.COSTUME_NOT_AVAILABLE,
                        "商品【" + costume.getName() + "】已下架");
            }

            return costume;

        } catch (BusinessException e) {
            LogUtil.error("COSTUME", "QUERY", "查询服装信息失败: costumeId={}, error={}",
                    costumeId, e.getMessage());
            throw e;
        } catch (Exception e) {
            LogUtil.error("COSTUME", "QUERY", "查询服装信息异常: costumeId={}", costumeId, e);
            throw CostumeException.of(CostumeErrorCode.QUERY_COSTUME_FAILED);
        }
    }

    /**
     * 参数校验
     */
    private void validateCalculateParam(RentalCalculateRequest request) {
        // 1. 非空校验
        if (request.getCartItemIds() == null || request.getCartItemIds().isEmpty()) {
            throw ValidationException.of(ValidationErrorCode.FIELD_REQUIRED, "购物车项不能为空");
        }

        if (request.getStartDate() == null) {
            throw ValidationException.of(ValidationErrorCode.FIELD_REQUIRED, "租赁开始日期不能为空");
        }

        if (request.getEndDate() == null) {
            throw ValidationException.of(ValidationErrorCode.FIELD_REQUIRED, "租赁结束日期不能为空");
        }

        // 2. 日期校验
        LocalDate today = LocalDate.now();
        if (request.getStartDate().isBefore(today)) {
            throw RentalException.of(RentalErrorCode.START_DATE_BEFORE_TODAY,
                    "租赁开始日期不能早于今天: " + today);
        }

        if (request.getEndDate().isBefore(request.getStartDate())) {
            throw RentalException.of(RentalErrorCode.END_DATE_BEFORE_START,
                    "租赁结束日期不能早于开始日期");
        }

        // 3. 租赁天数限制
        long rentalDays = ChronoUnit.DAYS.between(request.getStartDate(), request.getEndDate());
        if (rentalDays <= 0) {
            throw RentalException.of(RentalErrorCode.RENTAL_DAYS_INVALID, "租赁天数必须大于0");
        }

        long maxRentalDays = 365;
        if (rentalDays > maxRentalDays) {
            throw RentalException.of(RentalErrorCode.RENTAL_PERIOD_TOO_LONG,
                    "租赁天数不能超过" + maxRentalDays + "天");
        }

        // 4. 购物车项数量限制
        if (request.getCartItemIds().size() > 20) {
            throw CartException.of(CartErrorCode.CART_ITEM_LIMIT_EXCEEDED,
                    "一次最多计算20个商品的租金");
        }
    }
}